package com.littcore.saap.message.biz.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.mail.MessagingException;

import me.chanjar.weixin.common.exception.WxErrorException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;

import com.littcore.common.BeanManager;
import com.littcore.saap.assistant.po.UserFavourite;
import com.littcore.saap.assistant.service.IUserFavouriteService;
import com.littcore.saap.common.service.IEmailService;
import com.littcore.saap.common.service.ITemplateService;
import com.littcore.saap.common.vo.IUserInfo;
import com.littcore.saap.core.module.message.BaseMessage;
import com.littcore.saap.core.module.message.meta.MessageMeta;
import com.littcore.saap.core.module.message.meta.MessageMetaManager;
import com.littcore.saap.core.module.message.meta.MessageModule;
import com.littcore.saap.message.biz.IMessageBizService;
import com.littcore.saap.message.bo.MessageChannelBo;
import com.littcore.saap.message.dao.UserMessageDao;
import com.littcore.saap.message.module.MessageActor;
import com.littcore.saap.message.po.UserMessage;
import com.littcore.saap.message.service.IUserMessageSubService;
import com.littcore.saap.message.vo.UserMessageSubVo;
import com.littcore.saap.message.webservice.IMessageWebService;
import com.littcore.saap.system.service.IUserInfoService;
import com.littcore.saas.wechat.service.IWechatCpService;
import com.littcore.util.StringUtils;


/**
 * .
 * 
 * <pre><b>描述：</b>
 *    
 * </pre>
 * 
 * <pre><b>修改记录：</b>
 *    
 * </pre>
 * 
 * @author <a href="mailto:littcai@hotmail.com">蔡源</a>
 * @since 2015年10月27日
 * @version 1.0
 */
public class MessageBizServiceImpl implements IMessageBizService, IMessageWebService {
  
  public static final Logger logger = LoggerFactory.getLogger(MessageBizServiceImpl.class);
    
  @Resource
  private IUserMessageSubService userMessageSubService;
  @Resource
  private UserMessageDao userMessageDao;
  @Resource
  private IUserFavouriteService userFavouriteService;
  @Resource
  private IUserInfoService userInfoService;
  @Resource
  private ITemplateService templateService;
  @Resource
  private IEmailService emailService;
  @Resource
  private IWechatCpService wechatCpService;
  
  private String baseUrl;
  
  private String wechatCpBaseUrl;
  
  final ActorSystem system = ActorSystem.create("MySystem");
  final ActorRef actor;
  
  public MessageBizServiceImpl()
  {
    this.actor = system.actorOf(Props.create(MessageActor.class, this), "message");    
  }
  
  /**
   * 统一消息处理.
   * 若发送消息失败，应统一转存并通知给系统管理员，可转人工服务
   */
  public void onMessage(BaseMessage message)
  {    
    String metaCode = message.getMetaCode();
    logger.debug("receive message:{}", new Object[]{metaCode});
    
    IUserInfo fromUser = null;
    if(message.getFromBy()>0)
    {
      fromUser = userInfoService.find(message.getFromBy());
    }    
    
    //检查订阅的模块是否是记录模式的
    MessageModule module = MessageMetaManager.getInstance().getMessageModule(message.getModuleCode());
    //这里不会有follow的消息
    if(module.isRecordMode() && !"follow".equals(message.getMessageCode()))
    {
      List<UserFavourite> userFavouriteList = userFavouriteService.findByRecord(message.getModuleCode(), message.getRecordId(), message.getTenantId());
      if(userFavouriteList==null || userFavouriteList.isEmpty())
      {
        logger.debug("user doesn't subscribe the record, message won't be sent.");        
      }
      else 
      {
        for (UserFavourite userFavourite : userFavouriteList)
        {
          if(userFavourite.getCreateBy()==message.getReceiveBy() || userFavourite.getCreateBy()==message.getFromBy()) //关注人和消息发送人、接收人是同一个，忽略
          {
            continue;
          }
           BaseMessage messageClone = message.clone();  //复制消息对象并设置follow属性
           messageClone.setMessageCode("follow"); //重置消息编号为follow
           messageClone.setReceiveBy(userFavourite.getCreateBy());
           //检查关注者是否订阅
           UserMessageSubVo followMessageSub = userMessageSubService.find(messageClone.getReceiveBy(), messageClone.getTenantId(), messageClone.getModuleCode(), messageClone.getMessageCode());
           if(followMessageSub==null)
           {
             logger.debug("Can't find followMessageSub for tenant:{}, module:{}, message:{}", new Object[]{messageClone.getReceiveBy(), messageClone.getTenantId(), messageClone.getModuleCode(), messageClone.getMessageCode()});
             continue;
           }
           IUserInfo followUser = userInfoService.find(messageClone.getReceiveBy());
           String[] channels = StringUtils.split(followMessageSub.getChannels(), ',');
           
           for (String channel : channels)
           {
             Map<String, Object> propMap = new HashMap<String, Object>();
             propMap.put("channel", channel); 
             propMap.put("baseUrl", baseUrl);
             propMap.put("fromUser", fromUser);
             propMap.put("receiveUser", followUser);   
             propMap.put("message", message);
             
             propMap.put("wechatCpBaseUrl", this.wechatCpBaseUrl);
             
             MessageChannelBo bo = new MessageChannelBo();
             bo.setChannel(channel);
             bo.setMessage(messageClone);
             bo.setFromUser(fromUser);
             bo.setReceiveUser(followUser); //消息的接收人为follow
             bo.setPropMap(propMap);
             //改用akka实现基于actor的异步并发处理
             actor.tell(bo, ActorRef.noSender()); 
           }  
        }
      }
    }
    
      //FIXME 为了测试发给自己，正式环境屏蔽下面两行
//      if(message.getFromBy()==message.getReceiveBy()) //如果发件人跟收件人是一个，不发消息
//        return;
      
      if(message.getReceiveBy()<=0) //没有接收人也不用发
        return;
      IUserInfo receiveUser = userInfoService.find(message.getReceiveBy());    
      
      //根据消息接收人的订阅设置选择对应通道组织内容并进行发送   
      //强制发送的则不用关心用户是否订阅
      UserMessageSubVo userMessageSub = null;
      if(!message.isFourced())
      {
        userMessageSub = userMessageSubService.find(message.getReceiveBy(), message.getTenantId(), message.getModuleCode(), message.getMessageCode());
        if(userMessageSub==null)
        {
          logger.debug("Can't find userMessageSub for tenant:{}, module:{}, message:{}", new Object[]{message.getReceiveBy(), message.getTenantId(), message.getModuleCode(), message.getMessageCode()});
          return;
        }
      }
      MessageMeta messageMeta = MessageMetaManager.getInstance().getMessageMeta(message.getModuleCode(), message.getMessageCode());      
      
      String[] channels = message.isFourced()?messageMeta.getCheckedChannels():StringUtils.split(userMessageSub.getChannels(), ',');
      
      for (String channel : channels)
      {
        Map<String, Object> propMap = new HashMap<String, Object>();
        propMap.put("channel", channel); 
        propMap.put("baseUrl", baseUrl);
        propMap.put("fromUser", fromUser);
        propMap.put("receiveUser", receiveUser);     
        propMap.put("message", message);
        
        propMap.put("wechatCpBaseUrl", this.wechatCpBaseUrl);
        
        MessageChannelBo bo = new MessageChannelBo();
        bo.setChannel(channel);
        bo.setMessage(message);
        bo.setFromUser(fromUser);
        bo.setReceiveUser(receiveUser);
        bo.setPropMap(propMap);
        //改用akka实现基于actor的异步并发处理
        actor.tell(bo, ActorRef.noSender());  
    
      
//      
//      switch (channel)
//      {
//        case "email": 
//          this.sendEmail(message, receiveUser, messageName, propMap); 
//          break;
//        case "sms":
//          break;
//        case "wechat":          
//          this.sendWechat(message, receiveUser, messageName, propMap);
//          break;
//        case "ui":
//          this.sendUI(userMessageSub, message, receiveUser, messageName, propMap);
//          break;  
//        default:
//          
//      }
    }
        
    
    
  }
  
  /**
   * 发送邮件通知.
   * @param message
   * @param receiveUser
   * @param messageName
   * @param propMap
   */
  public void sendEmail(MessageChannelBo messageChannel)
  {
    BaseMessage message = messageChannel.getMessage();
    IUserInfo receiveUser = messageChannel.getReceiveUser();
    Map<String, Object> propMap = messageChannel.getPropMap();
    
    Locale locale = receiveUser.toLocale();
    String messageName = BeanManager.getMessage("message.module."+message.getModuleCode()+"."+message.getMessageCode(), locale);
    
    String content = templateService.genString(message.getMetaCode(), propMap);
    try
    {
      emailService.sendMime(receiveUser.getEmail(), messageName, content, content);
    } catch (MessagingException e)
    {
      logger.error("send email message error.", e);
    }
  }
  
  /**
   * 发送微信通知.
   * @param message
   * @param receiveUser
   * @param messageName
   * @param propMap
   */
  public void sendWechat(MessageChannelBo messageChannel)
  {
    BaseMessage message = messageChannel.getMessage();
    //IUserInfo receiveUser = messageChannel.getReceiveUser();
    Map<String, Object> propMap = messageChannel.getPropMap();   
    
    try
    {  
      String content = templateService.genString(message.getMetaCode(), propMap);
     
      wechatCpService.sendUserModuleTextMessage(message.getModuleCode(), content, true, ""+message.getReceiveBy());
      
    } catch (WxErrorException e)
    {
      logger.error("send wechat message error.", e);
    }
  }
  
  /**
   * 发送界面通知.
   * @param message
   * @param receiveUser
   * @param messageName
   * @param propMap
   */
  public void sendUI(MessageChannelBo messageChannel)
  {
    BaseMessage message = messageChannel.getMessage();
    IUserInfo receiveUser = messageChannel.getReceiveUser();
    Map<String, Object> propMap = messageChannel.getPropMap();
    
    String content = templateService.genString(message.getMetaCode(), propMap);
    UserMessage userMessage = new UserMessage();
    userMessage.setTenantId(message.getTenantId());
    userMessage.setModuleCode(message.getModuleCode());
    userMessage.setMessageCode(message.getMessageCode());
    userMessage.setPopup(messageChannel.isPopup());
    userMessage.setContent(content);
    userMessage.setReceiveBy(receiveUser.getId());
    userMessage.setCreateDatetime(new Date());
    
    userMessageDao.save(userMessage);
  }
  
  //private void 
  
  /* (non-Javadoc)
   * @see com.littcore.saap.message.biz.impl.IMessageBizService#sendMessage(com.littcore.saap.core.module.message.BaseMessage)
   */
  @Override
  public void publish(BaseMessage message)
  {        
    this.onMessage(message);
  }
  
  /**
   * 注册消息.
   * 
   * 用户可在个人中心选择订阅的消息列表
   */
  public void register()
  {
    
  } 
    
  /**
   * @return the wechatCpBaseUrl
   */
  public String getWechatCpBaseUrl()
  {
    return wechatCpBaseUrl;
  }

  
  /**
   * @param wechatCpBaseUrl the wechatCpBaseUrl to set
   */
  public void setWechatCpBaseUrl(String wechatCpBaseUrl)
  {
    this.wechatCpBaseUrl = wechatCpBaseUrl;
  }

  
  /**
   * @param baseUrl the baseUrl to set
   */
  public void setBaseUrl(String baseUrl)
  {
    this.baseUrl = baseUrl;
  }
  
}
